/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_asw_common.h"
#include "ctc_asw_security.h"
#include "ctc_asw_port.h"
#include "ctc_asw_vlan.h"
#include "ctc_asw_register.h"
#include "asw/include/drv_api.h"
uint32  stc_bitmap[CTC_MAX_LOCAL_CHIP_NUM][4] = {0};

/**
 @brief Configure learn limit

 @param[in] p_learn_limit    refer to ctc_security_learn_limit_t

 @return CTC_E_XXX
*/
int32
ctc_asw_mac_security_set_learn_limit(uint8 lchip, ctc_security_learn_limit_t* p_learn_limit)
{
    PortxLearnLimit_m     portx_learn_limit;
    MacLkupCtrl_m         mac_lkup_ctrl;
    uint32          cmd  = 0;
    int32           ret = 0;
    uint8           learn_en = 0;
    uint8           drop_en = 0;

    CTC_MAX_GPORT_CHECK(p_learn_limit->gport);
    if (CTC_IS_LINKAGG_PORT(p_learn_limit->gport))
    {
        p_learn_limit->gport = CTC_ASW_MAX_PORT_NUM_PER_CHIP + CTC_GPORT_LINKAGG_ID(p_learn_limit->gport);
    }

    CTC_API_LOCK(lchip);
    if (CTC_SECURITY_LEARN_LIMIT_TYPE_PORT == p_learn_limit->limit_type)
    {
        if ((p_learn_limit->gport) < CTC_ASW_MAX_PORT_NUM_PER_CHIP)
        {
            cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, p_learn_limit->gport, cmd, &mac_lkup_ctrl);
            switch (p_learn_limit->limit_action)
            {
                case CTC_MACLIMIT_ACTION_NONE:
                    learn_en = 1;
                    drop_en = 0;
                    break;
                case CTC_MACLIMIT_ACTION_FWD:           /*learning disable, forwarding*/
                    learn_en = 0;
                    drop_en = 0;
                    break;

                case CTC_MACLIMIT_ACTION_DISCARD:       /*learning enable, discard, not learnt*/
                    learn_en = 0;
                    drop_en = 1;
                    break;

                case CTC_MACLIMIT_ACTION_TOCPU:         /*learning enable, discard and to cpu, not learnt*/
                    learn_en = 1;
                    drop_en = 1;
                    break;
                default:
                    CTC_API_UNLOCK(lchip);
                    return CTC_E_INVALID_PARAM;
            }
            SetMacLkupCtrl(V,overlimitToDrop_f,&mac_lkup_ctrl,drop_en);
            SetMacLkupCtrl(V,overlimitToFifo_f,&mac_lkup_ctrl,learn_en);
            cmd = DRV_IOW(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = ret ? ret : DRV_IOCTL(lchip, p_learn_limit->gport, cmd, &mac_lkup_ctrl);
        }
        sal_memset(&portx_learn_limit, 0, sizeof(PortxLearnLimit_m));
        SetPortxLearnLimit(V,learningLimit_f,&portx_learn_limit,p_learn_limit->limit_num);
        cmd = DRV_IOW(PortxLearnLimit_t,DRV_ENTRY_FLAG);
        ret = ret ? ret :DRV_IOCTL(lchip,p_learn_limit->gport,cmd,&portx_learn_limit);
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_mac_security_get_learn_limit(uint8 lchip, ctc_security_learn_limit_t* p_learn_limit)
{
    PortxLearnLimit_m     portx_learn_limit;
    MacLkupCtrl_m         mac_lkup_ctrl;
    uint32          cmd  = 0;
    int32           ret = 0;
    uint8           learn_en = 0;
    uint8           drop_en = 0;

    CTC_MAX_GPORT_CHECK(p_learn_limit->gport);
    if (CTC_IS_LINKAGG_PORT(p_learn_limit->gport))
    {
        p_learn_limit->gport = CTC_ASW_MAX_PORT_NUM_PER_CHIP + CTC_GPORT_LINKAGG_ID(p_learn_limit->gport);
    }

    CTC_API_LOCK(lchip);
    if (CTC_SECURITY_LEARN_LIMIT_TYPE_PORT == p_learn_limit->limit_type)
    {
        if ((p_learn_limit->gport) < CTC_ASW_MAX_PORT_NUM_PER_CHIP)
        {
            cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, p_learn_limit->gport, cmd, &mac_lkup_ctrl);

            drop_en = GetMacLkupCtrl(V,overlimitToDrop_f,&mac_lkup_ctrl);
            learn_en = GetMacLkupCtrl(V,overlimitToFifo_f,&mac_lkup_ctrl);
            if ((0 == drop_en) && (1 == learn_en))
            {
                p_learn_limit->limit_action = CTC_MACLIMIT_ACTION_NONE;
            }
            else if ((0 == drop_en) && (0 == learn_en))
            {
                p_learn_limit->limit_action = CTC_MACLIMIT_ACTION_FWD;
            }
            else if ((1 == drop_en) && (0 == learn_en))
            {
                p_learn_limit->limit_action = CTC_MACLIMIT_ACTION_DISCARD;
            }
            else if ((1 == drop_en) && (1 == learn_en))
            {
                p_learn_limit->limit_action = CTC_MACLIMIT_ACTION_TOCPU;
            }
        }
        sal_memset(&portx_learn_limit, 0, sizeof(PortxLearnLimit_m));
        cmd = DRV_IOR(PortxLearnLimit_t,DRV_ENTRY_FLAG);
        ret = ret ? ret :DRV_IOCTL(lchip,p_learn_limit->gport,cmd,&portx_learn_limit);
        p_learn_limit->limit_num = GetPortxLearnLimit(V,learningLimit_f,&portx_learn_limit);
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  Set configure of storm ctl

 @param[in] stmctl_cfg   configure of storm ctl

 @return CTC_E_XXX

*/
int32
ctc_asw_storm_ctl_set_cfg(uint8 lchip, ctc_security_stmctl_cfg_t* stmctl_cfg)
{
    uint32    cmd  = 0;
    int32     ret  = 0;
    uint32    stc_index = 0;
    uint32    stmctl_en = 0;
    uint32    stmctl_base = 0;
    uint32    stc_base_mode  = 0;
    uint32    vlan_pro_index = 0;
    uint32    stmctl_en_port_down = 0;
    uint32    stmctl_en_vlan_down = 0;
    uint8     is_pps = 0;
    uint16    max_idx = 0;
    StcMeterCtrl_m     stc_meter_ctrl;

    CTC_PTR_VALID_CHECK(stmctl_cfg);

    sal_memset(&stc_meter_ctrl, 0, sizeof(stc_meter_ctrl));

    if (CTC_SECURITY_STORM_CTL_OP_PORT == stmctl_cfg->op)
    {
        CTC_MAX_GPORT_CHECK(stmctl_cfg->gport);
    }
    else
    {
        CTC_MAX_VALUE_CHECK(stmctl_cfg->vlan_id, CTC_MAX_VLAN_ID);
    }

    CTC_API_LOCK(lchip);
    if (CTC_SECURITY_STORM_CTL_OP_PORT == stmctl_cfg->op)
    {
        PortStcMapping_m   port_stc_mapping;
        sal_memset(&port_stc_mapping, 0, sizeof(port_stc_mapping));
        cmd = DRV_IOR(PortStcMapping_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, stmctl_cfg->gport, cmd, &port_stc_mapping);

        if (CTC_SECURITY_STORM_CTL_BCAST == stmctl_cfg->type)
        {
            SetPortStcMapping(V, bcStcEn_f, &port_stc_mapping, stmctl_cfg->storm_en);
            stmctl_base = GetPortStcMapping(V, bcStcIndex_f, &port_stc_mapping);
        }
        else if (CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST == stmctl_cfg->type)
        {
            SetPortStcMapping(V, dlfStcEn_f, &port_stc_mapping, stmctl_cfg->storm_en);
            stmctl_base = GetPortStcMapping(V, dlfStcIndex_f, &port_stc_mapping);
        }
        else if (CTC_SECURITY_STORM_CTL_KNOWN_MCAST == stmctl_cfg->type)
        {
            SetPortStcMapping(V, l2mcStcEn_f, &port_stc_mapping, stmctl_cfg->storm_en);
            stmctl_base = GetPortStcMapping(V, l2mcStcIndex_f, &port_stc_mapping);
        }
        else if (CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST == stmctl_cfg->type)
        {
            SetPortStcMapping(V, mlfStcEn_f, &port_stc_mapping, stmctl_cfg->storm_en);
            stmctl_base = GetPortStcMapping(V, mlfStcIndex_f, &port_stc_mapping);
        }
        else
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_NOT_SUPPORT;
        }
        cmd = DRV_IOW(PortStcMapping_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, stmctl_cfg->gport, cmd, &port_stc_mapping));

        cmd = DRV_IOR(PortStcMapping_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, stmctl_cfg->gport, cmd, &port_stc_mapping);
        stmctl_en_port_down = (GetPortStcMapping(V, mlfStcEn_f, &port_stc_mapping) || GetPortStcMapping(V, l2mcStcEn_f, &port_stc_mapping) || GetPortStcMapping(V, dlfStcEn_f, &port_stc_mapping) || 
        GetPortStcMapping(V, bcStcEn_f, &port_stc_mapping));

        cmd = DRV_IOR(PortStcMapping_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, stmctl_cfg->gport, cmd, &port_stc_mapping);
        stc_base_mode = GetPortStcMapping(V, dlfStcIndex_f, &port_stc_mapping)? 1 : 0;
        CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_get_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_EN, &stmctl_en));
        if ((stmctl_en) && (stmctl_cfg->storm_en))
        {
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_get_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_OFFSET, &stc_index));
        }
        else if ((stmctl_cfg->storm_en) && (stmctl_en == 0))
        {
            max_idx =  stc_base_mode ? 32 : 128;
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_bitmap_alloc(lchip, stc_bitmap[lchip], 0, max_idx, &stc_index));
            stc_index = stc_base_mode ? (stc_index << 2) : stc_index;
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_set_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_EN, stmctl_cfg->storm_en));
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_set_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_OFFSET, stc_index));
        }
        else if ((stmctl_en_port_down == 0) && (stmctl_en))
        {
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_set_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_EN, stmctl_en_port_down));
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_get_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_OFFSET, &stc_index));
            stc_index = stc_base_mode ? (stc_index >> 2) : stc_index;
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_bitmap_free(lchip, stc_bitmap[lchip], stc_index));
            CTC_API_UNLOCK(lchip);
            return CTC_E_NONE;
        }
        else if ((stmctl_en == 0) && (stmctl_cfg->storm_en == 0))
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_INVALID_CONFIG;
        }
    }
    else
    {
        IvtProfile_m        ivt_profile;
        IvtTable_m          ivt_table;
        GlbMeterCtrl_m     glb_meter_ctrl;
        sal_memset(&ivt_profile, 0, sizeof(ivt_profile));
        sal_memset(&ivt_table, 0, sizeof(ivt_table));
        sal_memset(&glb_meter_ctrl, 0, sizeof(glb_meter_ctrl));
        cmd = DRV_IOR(IvtTable_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, stmctl_cfg->vlan_id, cmd, &ivt_table);
        vlan_pro_index  = GetIvtTable(V, vlanProfileIndex_f, &ivt_table);
        cmd = DRV_IOR(IvtProfile_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, vlan_pro_index, cmd, &ivt_profile));
        cmd = DRV_IOR(GlbMeterCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, 0, cmd, &glb_meter_ctrl);
        if (CTC_SECURITY_STORM_CTL_BCAST == stmctl_cfg->type)
        {
            SetIvtProfile(V, bcStcEn_f, &ivt_profile, stmctl_cfg->storm_en);
            stmctl_base = GetGlbMeterCtrl(V, bcStcIndex_f, &glb_meter_ctrl);
        }
        else if (CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST == stmctl_cfg->type)
        {
            SetIvtProfile(V, dlfStcEn_f, &ivt_profile, stmctl_cfg->storm_en);
            stmctl_base = GetGlbMeterCtrl(V, dlfStcIndex_f, &glb_meter_ctrl);
        }
        else if (CTC_SECURITY_STORM_CTL_KNOWN_MCAST == stmctl_cfg->type)
        {
            SetIvtProfile(V, l2mcStcEn_f, &ivt_profile, stmctl_cfg->storm_en);
            stmctl_base = GetGlbMeterCtrl(V, l2mcStcIndex_f, &glb_meter_ctrl);
        }
        else if (CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST == stmctl_cfg->type)
        {
            SetIvtProfile(V, mlfStcEn_f, &ivt_profile, stmctl_cfg->storm_en);
            stmctl_base = GetGlbMeterCtrl(V, mlfStcIndex_f, &glb_meter_ctrl);
        }
        else
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_NOT_SUPPORT;
        }
        cmd = DRV_IOW(IvtProfile_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, vlan_pro_index, cmd, &ivt_profile));
        cmd = DRV_IOR(IvtTable_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, stmctl_cfg->vlan_id, cmd, &ivt_table);
        vlan_pro_index  = GetIvtTable(V, vlanProfileIndex_f, &ivt_table);
        cmd = DRV_IOR(IvtProfile_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, vlan_pro_index, cmd, &ivt_profile));
        stmctl_en_vlan_down  = (GetIvtProfile(V, mlfStcEn_f, &ivt_profile) || GetIvtProfile(V, l2mcStcEn_f, &ivt_profile) || GetIvtProfile(V, dlfStcEn_f, &ivt_profile) || GetIvtProfile(V, bcStcEn_f, &ivt_profile));

        cmd = DRV_IOR(GlbMeterCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, 0, cmd, &glb_meter_ctrl);
        stc_base_mode = GetGlbMeterCtrl(V, dlfStcIndex_f, &glb_meter_ctrl)? 1 : 0;

        CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_get_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_EN, &stmctl_en));
        if ((stmctl_en) && (stmctl_cfg->storm_en))
        {
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_get_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_PTR, &stc_index));
        }
        else if ((stmctl_cfg->storm_en) && (stmctl_en == 0))
        {
            max_idx =  stc_base_mode ? 32 : 128;
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_bitmap_alloc(lchip, stc_bitmap[lchip], 0, max_idx, &stc_index));
            stc_index = stc_base_mode ? (stc_index << 2) : stc_index;
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_set_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_EN, stmctl_cfg->storm_en));
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_set_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_PTR, stc_index));
        }
        else if ((stmctl_en_vlan_down == 0) && (stmctl_en))
        {
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_set_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_EN, stmctl_en_vlan_down));
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_get_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_PTR, &stc_index));
            stc_index = stc_base_mode ? (stc_index >> 2) : stc_index;
            CTC_ERROR_RETURN_UNLOCK(_ctc_asw_bitmap_free(lchip, stc_bitmap[lchip], stc_index));
            CTC_API_UNLOCK(lchip);
            return CTC_E_NONE;
        }
        else if ((stmctl_en == 0) && (stmctl_cfg->storm_en == 0))
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_INVALID_CONFIG;
        }
    }

    stc_index = stmctl_base + stc_index;
    is_pps = (CTC_SECURITY_STORM_CTL_MODE_PPS == stmctl_cfg->mode)? 1 : 0;
    cmd = DRV_IOR(StcMeterCtrl_t, DRV_ENTRY_FLAG);
    ret = ret? ret : DRV_IOCTL(lchip, stc_index, cmd, &stc_meter_ctrl);
    SetStcMeterCtrl(V, meterMode_f, &stc_meter_ctrl, is_pps);
    if (is_pps)
    {
        CTC_MAX_VALUE_CHECK_UNLOCK(stmctl_cfg->threshold, 0x7FFFF);
        SetStcMeterCtrl(V, bucketGrain_f, &stc_meter_ctrl, 2);
        SetStcMeterCtrl(V, refreshCnt_f, &stc_meter_ctrl, stmctl_cfg->threshold >> 2);
    }
    else
    {
        CTC_MAX_VALUE_CHECK_UNLOCK(stmctl_cfg->threshold, 0x3FFFFF);
        SetStcMeterCtrl(V, bucketGrain_f, &stc_meter_ctrl, 0);
        SetStcMeterCtrl(V, refreshCnt_f, &stc_meter_ctrl, (stmctl_cfg->threshold >> 3));
    }
    SetStcMeterCtrl(V, meterEn_f, &stc_meter_ctrl, 1);
    SetStcMeterCtrl(V, dropThd_f, &stc_meter_ctrl, 0xFFF);
    cmd = DRV_IOW(StcMeterCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : (DRV_IOCTL(lchip, stc_index, cmd, &stc_meter_ctrl));
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  Get configure of storm ctl

 @param[out] stmctl_cfg  configure of storm ctl

 @return CTC_E_XXX

*/
int32
ctc_asw_storm_ctl_get_cfg(uint8 lchip, ctc_security_stmctl_cfg_t* stmctl_cfg)
{
    uint32  cmd  = 0;
    int32   ret  = 0;
    uint8   is_pps    = 0;
    uint8   storm_en = 0;
    uint8   stmctl_base = 0;
    uint32  sw_storm_en = 0;
    uint32  stc_index = 0;
    uint32  threshold = 0;
    uint32  vlan_pro_index = 0;
    StcMeterCtrl_m     stc_meter_ctrl;
    PortStcMapping_m   port_stc_mapping;
    IvtTable_m          ivt_table;
    GlbMeterCtrl_m     glb_meter_ctrl;
    IvtProfile_m        ivt_profile;

    CTC_PTR_VALID_CHECK(stmctl_cfg);

    sal_memset(&stc_meter_ctrl, 0, sizeof(stc_meter_ctrl));
    sal_memset(&port_stc_mapping, 0, sizeof(port_stc_mapping));
    sal_memset(&ivt_profile, 0, sizeof(ivt_profile));
    sal_memset(&ivt_table, 0, sizeof(ivt_table));
    sal_memset(&glb_meter_ctrl, 0, sizeof(glb_meter_ctrl));

    if (CTC_SECURITY_STORM_CTL_OP_PORT == stmctl_cfg->op)
    {
        CTC_MAX_GPORT_CHECK(stmctl_cfg->gport);
    }
    else
    {
        CTC_MAX_VALUE_CHECK(stmctl_cfg->vlan_id, CTC_MAX_VLAN_ID);
    }

    CTC_API_LOCK(lchip);
	if (CTC_SECURITY_STORM_CTL_OP_PORT == stmctl_cfg->op)
	{
		cmd = DRV_IOR(PortStcMapping_t, DRV_ENTRY_FLAG);
		ret = DRV_IOCTL(lchip, stmctl_cfg->gport, cmd, &port_stc_mapping);
		if (CTC_SECURITY_STORM_CTL_BCAST == stmctl_cfg->type)
		{
			stmctl_base = GetPortStcMapping(V,bcStcIndex_f,&port_stc_mapping);
			storm_en = GetPortStcMapping(V,bcStcEn_f,&port_stc_mapping);
		}
		else if (CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST == stmctl_cfg->type)
		{
			stmctl_base = GetPortStcMapping(V,dlfStcIndex_f,&port_stc_mapping);
			storm_en = GetPortStcMapping(V,dlfStcEn_f,&port_stc_mapping);
		}
		else if (CTC_SECURITY_STORM_CTL_KNOWN_MCAST == stmctl_cfg->type)
		{
			stmctl_base = GetPortStcMapping(V,l2mcStcIndex_f,&port_stc_mapping);
			storm_en = GetPortStcMapping(V,l2mcStcEn_f,&port_stc_mapping);
		}
		else if (CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST == stmctl_cfg->type)
		{
			stmctl_base = GetPortStcMapping(V,mlfStcIndex_f,&port_stc_mapping);
			storm_en = GetPortStcMapping(V,mlfStcEn_f,&port_stc_mapping);
		}
		else
		{
			CTC_API_UNLOCK(lchip);
			return CTC_E_NOT_SUPPORT;
		}
		CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_get_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_EN, &sw_storm_en));
	 	CTC_ERROR_RETURN_UNLOCK(_ctc_asw_port_get_internal_property(lchip, stmctl_cfg->gport, CTC_PORT_INT_PROP_STMCTL_OFFSET, &stc_index));
	}
	else
	{
		cmd = DRV_IOR(IvtTable_t, DRV_ENTRY_FLAG);
		ret = DRV_IOCTL(lchip, stmctl_cfg->vlan_id, cmd, &ivt_table);
		vlan_pro_index	= GetIvtTable(V, vlanProfileIndex_f, &ivt_table);
		cmd = DRV_IOR(IvtProfile_t, DRV_ENTRY_FLAG);
		ret = ret ? ret : (DRV_IOCTL(lchip, vlan_pro_index, cmd, &ivt_profile));
		cmd = DRV_IOR(GlbMeterCtrl_t, DRV_ENTRY_FLAG);
		ret = ret?ret:DRV_IOCTL(lchip, 0, cmd, &glb_meter_ctrl);
		if (CTC_SECURITY_STORM_CTL_BCAST == stmctl_cfg->type)
		{
			storm_en = GetIvtProfile(V, bcStcEn_f, &ivt_profile);
			stmctl_base = GetGlbMeterCtrl(V,bcStcIndex_f,&glb_meter_ctrl);
		}
		else if (CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST == stmctl_cfg->type)
		{
            storm_en = GetIvtProfile(V, dlfStcEn_f, &ivt_profile);
            stmctl_base = GetGlbMeterCtrl(V,dlfStcIndex_f,&glb_meter_ctrl);
		}
		else if (CTC_SECURITY_STORM_CTL_KNOWN_MCAST == stmctl_cfg->type)
		{
            storm_en = GetIvtProfile(V, l2mcStcEn_f, &ivt_profile);
            stmctl_base = GetGlbMeterCtrl(V,l2mcStcIndex_f,&glb_meter_ctrl);
		}
		else if (CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST == stmctl_cfg->type)
		{
            storm_en = GetIvtProfile(V, mlfStcEn_f, &ivt_profile);
            stmctl_base = GetGlbMeterCtrl(V,mlfStcIndex_f,&glb_meter_ctrl);
		}
		else
		{
			CTC_API_UNLOCK(lchip);
			return CTC_E_NOT_SUPPORT;
		}
		CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_get_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_EN, &sw_storm_en));
	  	CTC_ERROR_RETURN_UNLOCK(_ctc_asw_vlan_get_internal_property(lchip, stmctl_cfg->vlan_id, CTC_VLAN_INT_PROP_VLAN_STORM_CTL_PTR, &stc_index));
	}

    stmctl_cfg->storm_en = ((0 == sw_storm_en) || (0 == storm_en))? 0: 1;
    if (1 == stmctl_cfg->storm_en)
    {
        stc_index = stmctl_base + stc_index;
        cmd = DRV_IOR(StcMeterCtrl_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, stc_index, cmd, &stc_meter_ctrl);
        is_pps = GetStcMeterCtrl(V,meterMode_f,&stc_meter_ctrl);
        threshold = GetStcMeterCtrl(V,refreshCnt_f,&stc_meter_ctrl);
        if(is_pps)
        {
            stmctl_cfg->mode = CTC_SECURITY_STORM_CTL_MODE_PPS;
            stmctl_cfg->threshold = threshold<<2;
        }
        else
        {
            stmctl_cfg->mode = CTC_SECURITY_STORM_CTL_MODE_KBPS;
            stmctl_cfg->threshold = threshold<<3;
        }
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  Set global configure of storm ctl

 @param[out] p_glb_cfg  global configure of storm ctl

 @return CTC_E_XXX

*/
int32
ctc_asw_storm_ctl_set_global_cfg(uint8 lchip, ctc_security_stmctl_glb_cfg_t* p_glb_cfg)
{
    uint32  cmd  = 0;
    int32   ret  = 0;
    int32   stc_index  = 0;
    StcMeterCtrl_m     stc_meter_ctrl;

    CTC_API_LOCK(lchip);
    for (stc_index = 0; stc_index<128; stc_index++)
    {
        cmd = DRV_IOR(StcMeterCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, stc_index, cmd, &stc_meter_ctrl);
        SetStcMeterCtrl(V,meterDelta_f,&stc_meter_ctrl,p_glb_cfg->ipg_en ? 0:1);
        cmd = DRV_IOW(StcMeterCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, stc_index, cmd, &stc_meter_ctrl));
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  Get global configure of storm ctl

 @param[out] p_glb_cfg  global configure of storm ctl

 @return CTC_E_XXX

*/
int32
ctc_asw_storm_ctl_get_global_cfg(uint8 lchip, ctc_security_stmctl_glb_cfg_t* p_glb_cfg)
{
    uint32  cmd  = 0;
    int32   ret  = 0;
    StcMeterCtrl_m     stc_meter_ctrl;

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(StcMeterCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, 0, cmd, &stc_meter_ctrl);
    p_glb_cfg->ipg_en = GetStcMeterCtrl(V,meterDelta_f,&stc_meter_ctrl)?0:1;
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  Configure port based  mac limit

 @param[in] gport       global port

 @param[in] action      refer to ctc_maclimit_action_t

 @return CTC_E_XXX
*/
int32
ctc_asw_mac_security_set_port_mac_limit(uint8 lchip, uint32 gport, ctc_maclimit_action_t action)
{
    uint32  cmd  = 0;
    int32   ret  = 0;
    MacLkupCtrl_m         mac_lkup_ctrl;
    uint8 drop_en = 0;
    uint8 learn_en = 0;

    if (CTC_IS_LINKAGG_PORT(gport))
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &mac_lkup_ctrl);
    switch (action)
    {
        case CTC_MACLIMIT_ACTION_NONE:
            drop_en = 0;
            learn_en = 1;
            break;
        case CTC_MACLIMIT_ACTION_FWD:           /*learning disable, forwarding*/
            drop_en = 0;
            learn_en = 0;
            break;

        case CTC_MACLIMIT_ACTION_DISCARD:       /*learning enable, discard, not learnt*/
            drop_en = 1;
            learn_en = 0;
            break;

        case CTC_MACLIMIT_ACTION_TOCPU:         /*learning enable, discard and to cpu, not learnt*/
            drop_en = 1;
            learn_en = 1;
            break;

        default:
            CTC_API_UNLOCK(lchip);
            return CTC_E_INVALID_PARAM;
    }
    SetMacLkupCtrl(V,overlimitToDrop_f,&mac_lkup_ctrl,drop_en);
    SetMacLkupCtrl(V,overlimitToFifo_f,&mac_lkup_ctrl,learn_en);
    cmd = DRV_IOW(MacLkupCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &mac_lkup_ctrl);
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  get the configure  of port based  mac limit

 @param[in] gport       global port

 @param[in] action      refer to ctc_maclimit_action_t

 @return CTC_E_XXX
*/
int32
ctc_asw_mac_security_get_port_mac_limit(uint8 lchip, uint32 gport, ctc_maclimit_action_t* action)
{
    uint32  cmd  = 0;
    int32   ret  = 0;
    uint32  mac_security_discard_en = 0;
    uint32  security_excp_en = 0;
    MacLkupCtrl_m   mac_lkup_ctrl;

    if (CTC_IS_LINKAGG_PORT(gport))
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip,gport, cmd, &mac_lkup_ctrl);
    mac_security_discard_en = GetMacLkupCtrl(V,overlimitToDrop_f,&mac_lkup_ctrl);
    security_excp_en = GetMacLkupCtrl(V,overlimitToFifo_f,&mac_lkup_ctrl);
    if (mac_security_discard_en == FALSE && security_excp_en == FALSE)
    {
        *action = CTC_MACLIMIT_ACTION_FWD;
    }
    else if (mac_security_discard_en == TRUE && security_excp_en == FALSE)
    {
        *action = CTC_MACLIMIT_ACTION_DISCARD;
    }
    else if (mac_security_discard_en == TRUE && security_excp_en == TRUE)
    {
        *action = CTC_MACLIMIT_ACTION_TOCPU;
    }
    else if (mac_security_discard_en == FALSE && security_excp_en == TRUE)
    {
        *action = CTC_MACLIMIT_ACTION_NONE;
    }
    else
    {
        CTC_API_UNLOCK(lchip);
        return CTC_E_INVALID_PARAM;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief  Init security module

 @return CTC_E_XXX

*/
int32
ctc_asw_security_init(uint8 lchip, void* security_global_cfg)
{
    uint32          cmd  = 0;
    int32           ret = 0;
    uint32    stmctl_base = 0;
    int32     i = 0;
    PortStcMapping_m   port_stc_mapping;
    GlbMeterCtrl_m     glb_meter_ctrl;
    ctc_security_global_cfg_t *p_glb_cfg = security_global_cfg;
    SecurityFilterRule_m security_filter_rule;
    uint8 qos_mode = 0;

    if (NULL != p_glb_cfg)
    {
        qos_mode = p_glb_cfg->qos_mode;
    }
    sal_memset(&security_filter_rule, 0, sizeof(security_filter_rule));

    for (i=0;i<CTC_ASW_MAX_PORT_NUM_PER_CHIP;i++)
    {
        stmctl_base = 0;
        cmd = DRV_IOR(PortStcMapping_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, i, cmd, &port_stc_mapping);
        SetPortStcMapping(V,bcStcIndex_f,&port_stc_mapping,stmctl_base);
        stmctl_base = qos_mode ? 0 : 1;
        SetPortStcMapping(V,dlfStcIndex_f,&port_stc_mapping,stmctl_base);
        stmctl_base = qos_mode ? 0 : 2;
        SetPortStcMapping(V,l2mcStcIndex_f,&port_stc_mapping,stmctl_base);
        stmctl_base = qos_mode ? 0 : 3;
        SetPortStcMapping(V,mlfStcIndex_f,&port_stc_mapping,stmctl_base);
        cmd = DRV_IOW(PortStcMapping_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, i, cmd, &port_stc_mapping));
    }
    stmctl_base = 0;
    cmd = DRV_IOR(GlbMeterCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, 0, cmd, &glb_meter_ctrl);
    SetGlbMeterCtrl(V,bcStcIndex_f,&glb_meter_ctrl,stmctl_base);
    stmctl_base = qos_mode ? 0 : 1;
    SetGlbMeterCtrl(V,dlfStcIndex_f,&glb_meter_ctrl,stmctl_base);
    stmctl_base = qos_mode ? 0 : 2;
    SetGlbMeterCtrl(V,l2mcStcIndex_f,&glb_meter_ctrl,stmctl_base);
    stmctl_base = qos_mode ? 0 : 3;
    SetGlbMeterCtrl(V,mlfStcIndex_f,&glb_meter_ctrl,stmctl_base);
    cmd = DRV_IOW(GlbMeterCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : (DRV_IOCTL(lchip, 0, cmd, &glb_meter_ctrl));
    SetSecurityFilterRule(V,icmpv6Fragment_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,icmpv6Longping_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,icmpv4Longping_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,ipFragErr_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,icmpv4Fragment_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tcpFragerror_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tinyTcp_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tcpSynerror_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tcpSynfinscan_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tcpXmasscan_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tcpNullscan_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,udpBlat_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,tcpBlat_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,ipLand_f,&security_filter_rule,1);
    SetSecurityFilterRule(V,macLand_f,&security_filter_rule,1);
    cmd = DRV_IOW(SecurityFilterRule_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : (DRV_IOCTL(lchip, 0, cmd, &security_filter_rule));

    return ret;
}

int32
ctc_asw_security_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}
